using System;
using System.Text;

namespace BizElements.Core
{
	// All predicates have internal constructors. Use factory to create a predicate.

	/// <summary>
	/// Base class for all predicate classes. Provides common logic for the inherited classes.
	/// </summary>
	/// <remarks>Predicate is an expression that evaluates to TRUE, FALSE, or UNKNOWN. 
	/// Predicates are used in the search condition of WHERE and HAVING clauses.
	/// <seealso cref="PredicateFactory"/><seealso cref="SearchCondition"/></remarks>
	[Serializable]
	public abstract class PredicateBase : IRenderSql
	{
        #region Properties.

        /// <summary>
		/// Gets items required by this predicate.
		/// </summary>
        public PredicateItem[] PredicateItems { get; protected set; }

		/// <summary>
		/// Gets the value that specifies whether the predicate is negated.
		/// </summary>
        public bool Negate { get; protected set; }

        #endregion

        #region Abstract Render - must be implemented in derived classes.

        /// <summary>
		/// Renders predicate as SQL statement.
		/// </summary>
		/// <param name="dbms">Target DBMS.</param>
		/// <param name="output">StringBuilder to which SQL is appended.</param>
		/// <param name="parameters">SQL parameter collection to which the object's and its children's
		/// parameters are added. After the rendering is done the collection contains all parameters with unique names.</param>
		public abstract void Render(DbmsType dbms, StringBuilder output, DbParameterCollection parameters);

		#endregion

        #region (SearchCondition) cast operator and ToSearchCondition() alternate method.

        /// <summary>
		/// Converts a predicate to a search condition.
		/// </summary>
		/// <param name="predicate">Predicate.</param>
		/// <returns>Search condition which contains the given predicate.</returns>
		public static explicit operator SearchCondition(PredicateBase predicate)
		{
			return new SearchCondition(predicate);
        }

        /// <summary>
        /// Converts a predicate to a search condition.
        /// </summary>
        /// <param name="predicate">Predicate.</param>
        /// <returns>Search condition which contains the given predicate.</returns>
        public static SearchCondition ToSearchCondition(PredicateBase predicate)
        {
            return new SearchCondition(predicate);
        }

        #endregion
    }	
}
